
package com.monlyu.bo;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.io.FileUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.google.common.collect.Lists;
import com.monlyu.action.solution.EditSolutionAction;
import com.monlyu.annotation.ActionAnno;
import com.monlyu.bo.model.AuditList;
import com.monlyu.bo.model.ImageModel;
import com.monlyu.bo.model.ManscripModel;
import com.monlyu.exception.MsgException;
import com.monlyu.model.SearchSolutionModel;
import com.monlyu.model.ShowSolutionModel;
import com.monlyu.util.ArrayUtil;
import com.monlyu.util.DateUtil;
import com.monlyu.util.FtlUtil;
import com.monlyu.util.JsonUtil;
import com.monlyu.util.StringUtil;
import com.monlyu.util.WebOptUtil;
import com.monlyu.util.ZipUtil;
import com.monlyu.varables.PermVar;
import com.monlyu.vo.Attachment;
import com.monlyu.vo.ManuScAudit;
import com.monlyu.vo.Manuscript;
import com.monlyu.vo.Manuscript2Image;
import com.monlyu.vo.Solution;
import com.monlyu.vo.SolutionContent;
import com.monlyu.vo.SolutionItem;
import com.monlyu.vo.SolutionReview;
import com.monlyu.vo.User;

/*******************************************************************************
 * <b>功能描述☞</b><br>
 * <b>开发公司☞</b>重庆唯尼科技有限公司<br>
 * <b>版权☞</b>本文件归重庆唯尼科技有限公司所有<br>
 * <b>项目名☞</b>news_cd<br>
 * <b>文件路径☞</b>com.monlyu.bo.SolutionBo.java<br>
 * <b>开发日期☞</b>2011-6-25 <br>
 * 
 * @author chendan
 * @since JDK 5
 * @version 1.0.8
 ******************************************************************************/
@Repository(value = "solutionBo")
public class SolutionBo extends BaseBo {

    private ProgrammingBo programmingBo;
    private AttachmentBo attachmentBo;
    private RoleBo roleBo;

    public void setRoleBo(RoleBo roleBo){
        this.roleBo = roleBo;
    }

    public void setAttachmentBo(AttachmentBo attachmentBo){
        this.attachmentBo = attachmentBo;
    }

    /**
     * 查询编辑方案
     * 
     * @param solutionModel
     * @param action
     * @return
     * @since chendan 2011-6-25
     */
    public List<ShowSolutionModel> searchSolution(SearchSolutionModel solutionModel, String action){
        List<ShowSolutionModel> results = Lists.newArrayList();
        StringBuffer hql = new StringBuffer();
        List<Object> args = new ArrayList<Object>();
        // hql.append("select s.*,sr.* from com.monlyu.vo.Solution
        // s,com.monlyu.vo.SolutionReview sr where s.id=sr.solution.id ");
        hql.append("from com.monlyu.vo.Solution s where 1=1 ");
        if (solutionModel != null) {
            if (solutionModel.getStatus() != -100) {
                hql.append(" and status=? ");
                args.add(solutionModel.getStatus());
            }

            if (!StringUtil.isEmpty(solutionModel.getName())) {
                hql.append(" and s.name like ?");
                args.add("%" + solutionModel.getName() + "%");
            }
            if (!StringUtil.isEmpty(solutionModel.getIssue())) {
                hql.append(" and s.issue=?");
                args.add(solutionModel.getIssue());
            }
            if (solutionModel.getBeginDate() != null) {
                hql.append(" and s.recorderDate>=?");
                args.add(solutionModel.getBeginDate());
            }
            if (solutionModel.getEndDate() != null) {
                hql.append(" and s.recorderDate<?");
                args.add(DateUtil.addDay(solutionModel.getEndDate(), 1));
            }
            if (solutionModel.getUbeginDate() != null) {
                hql.append(" and s.date>=?");
                args.add(solutionModel.getUbeginDate());
            }
            if (solutionModel.getUendDate() != null) {
                hql.append(" and s.date<?");
                args.add(DateUtil.addDay(solutionModel.getUendDate(), 1));
            }
            if (solutionModel.getUserId() != null && !"0".equals(solutionModel.getUserId().toString())) {
                hql.append(" and s.recorder.id=?");
                args.add(solutionModel.getUserId());
            }
        }

        List result = dao.find(hql.toString(), args.toArray());
        for (Iterator<Solution> it = result.iterator(); it.hasNext();) {
            Solution solution = it.next();
            ShowSolutionModel sModel = new ShowSolutionModel();
            sModel.setSolution(solution);
            // String review = "from com.monlyu.vo.SolutionReview sr where
            // sr.solution.id=?";
            // SolutionReview sReview = (SolutionReview) dao.findOne(review,
            // solution.getId());
            // sModel.setSReview(sReview);
            sModel.setAction(action);
            results.add(sModel);
        }
        return results;
    }

    /**
     * 查询编辑方案的内容
     * 
     * @param solutionId
     * @return
     * @since chendan 2011-6-25
     */
    public ShowSolutionModel getShowSolution(Long solutionId){
        ShowSolutionModel sModel = new ShowSolutionModel();
        sModel.setSolution(dao.get(Solution.class, solutionId));
        sModel.setReviewList(getSReviews(solutionId));
        sModel.setContentList(getSContents(solutionId));
        return sModel;
    }

    /**
     * 查询编辑方案审核列表
     * 
     * @param solutionId
     * @return
     * @since chendan 2011-6-30
     */
    public List<SolutionReview> getSReviews(Long solutionId){
        String review = "from com.monlyu.vo.SolutionReview sr where sr.solution.id=? order by sr.id";
        List result = dao.find(review, solutionId);
        List<SolutionReview> reviewList = new ArrayList<SolutionReview>();
        for (Iterator<SolutionReview> it = result.iterator(); it.hasNext();) {
            SolutionReview review2 = it.next();
            reviewList.add(review2);
        }
        return reviewList;
    }

    /**
     * 查询编辑方案内容
     * 
     * @param solutionId
     * @return
     * @since chendan 2011-6-30
     */
    public List<SolutionContent> getSContents(Long solutionId){
        String content = "from com.monlyu.vo.SolutionContent sc where sc.solutionItem.solution.id=? order by sc.id";
        List result = dao.find(content, solutionId);
        List<SolutionContent> list = new ArrayList<SolutionContent>();
        for (Iterator<SolutionContent> it = result.iterator(); it.hasNext();) {
            SolutionContent sContent = it.next();
            list.add(sContent);
        }
        return list;
    }

    /**
     * 导出编辑方案内容
     * 
     * @param solutionId
     * @return
     * @throws Exception
     * @since chendan 2011-6-26
     */
    public InputStream exportSolution(Long solutionId) throws Exception{
        if (!roleBo.checkPermission(PermVar.SOLUTION_EXPORT)) {
            throw new MsgException("对不起，您没有编辑方案导出的权限。");
        }
        ShowSolutionModel solutionModel = getShowSolution(solutionId);
        // 拿到导出的表样对象流
        String url = WebOptUtil.APP_ARGS.getWebFileDir() + "common/report/solution.xls";
        InputStream is = new FileInputStream(url);
        HSSFWorkbook wb = new HSSFWorkbook(is);
        is.close();
        HSSFSheet sheet = wb.getSheetAt(0);
        HSSFCellStyle style = wb.createCellStyle();
        // style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        // style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        // style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        // style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 居中
        HSSFFont font = wb.createFont();
        font.setFontHeightInPoints((short) 15);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);// 加粗
        font.setFontName("黑体");
        style.setFont(font);
        style.setWrapText(true);
        int rowNum = 0;
        short celNum = 0;
        HSSFRow row = sheet.createRow(rowNum++);
        // 下面开始组装数据
        HSSFCell cell = row.createCell(celNum);
        cell.setCellValue(new HSSFRichTextString("《"
            + solutionModel.getSolution().getName()
            + "》编辑方案   第"
            + solutionModel.getSolution().getIssue()
            + "期（"
            + DateUtil.format(solutionModel.getSolution().getDate(), "MM月dd日")
            + "出版）  "
            + DateUtil.format(solutionModel.getSolution().getRecorderDate(), "yyyy年MM月dd日")));
        cell.setCellStyle(style);
        // 第二行
        row = sheet.createRow(rowNum++);
        cell = row.createCell(celNum);
        // cell.setCellValue(new HSSFRichTextString("领导意见："
        // + (solutionModel.getSReview() == null ? "" : solutionModel
        // .getSReview().getAuditRemark())));
        cell.setCellStyle(style);
        // 第三行
        rowNum++;
        // 第四行
        HSSFCellStyle style1 = wb.createCellStyle();
        style1.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style1.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style1.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style1.setBorderTop(HSSFCellStyle.BORDER_THIN);
        HSSFFont font1 = wb.createFont();
        font1.setFontHeightInPoints((short) 11);
        style1.setFont(font1);
        for (Iterator<SolutionContent> it = solutionModel.getContentList().iterator(); it.hasNext();) {
            SolutionContent content = it.next();
            celNum = 0;
            row = sheet.createRow(rowNum++);
            cell = row.createCell(celNum++, HSSFCell.CELL_TYPE_STRING);
            cell.setCellValue(new HSSFRichTextString(content.getPage())); // 页码
            cell.setCellStyle(style1);
            cell = row.createCell(celNum++, HSSFCell.CELL_TYPE_STRING);
            // cell.setCellValue(new HSSFRichTextString((String)
            // enumsBo.getEnumValue(content.getColumn()))); // 栏目
            cell.setCellStyle(style1);
            cell = row.createCell(celNum++, HSSFCell.CELL_TYPE_STRING);
            cell.setCellValue(new HSSFRichTextString(content.getManuscript().getTitle())); // 稿件
            cell.setCellStyle(style1);
            cell = row.createCell(celNum++, HSSFCell.CELL_TYPE_STRING);
            // cell.setCellValue(new
            // HSSFRichTextString(content.getEditor().getName())); // 编辑
            cell.setCellStyle(style1);
        }
        return is;
    }

    /**
     * 查询编辑方案的内容
     * 
     * @param solutionId
     * @return
     * @since chendan 2011-6-26
     */
    @SuppressWarnings("unchecked")
    public List<SolutionContent> getContent(Long solutionId){
        String content = "from com.monlyu.vo.SolutionItem sc where sc.solution.id=? order by sc.id";
        List<SolutionItem> result = dao.find(content, solutionId);
        Criteria criteria = dao.initCriteria(SolutionContent.class);
        if (result.size() == 0)
            return Collections.EMPTY_LIST;
        List<Long> ids = new ArrayList<Long>();
        for (SolutionItem solutionItem : result) {
            ids.add(solutionItem.getId());
        }
        criteria.add(Restrictions.in("solutionItem.id", ids));
        return criteria.list();
    }

    /**
     * 编辑方案新增
     * 
     * @param solution
     * @since chendan 2011-6-26
     */
    public void createSolution(Solution solution){
        if (!roleBo.checkPermission(PermVar.SOLUTION_ADD)) {
            throw new MsgException("对不起，您没有编辑方案新增的权限。");
        }
        solution.setRecorder(curUser());
        solution.setRecorderDate(DateUtil.now());
        solution.setStatus(0);
        dao.insertOrUpdate(solution);
    }

    /**
     * 获取一条记录
     * 
     * @return
     */
    public SolutionItem getSolutionItem(Long solutionId, int order){
        Criteria criteria = dao.initCriteria(SolutionItem.class);
        criteria.add(Restrictions.eq("solution.id", solutionId));
        criteria.add(Restrictions.eq("order", order));
        if (criteria.list().size() == 0) {
            return null;
        }
        return (SolutionItem) criteria.list().get(0);
    }

    /**
     * 保存编辑方案内容
     * 
     * @param content
     * @since chendan 2011-6-26
     */
    public void createContent(SolutionContent content){
        // content.setSolution(dao.get(Solution.class,
        // content.getSolution().getId()));
        if (!roleBo.checkPermission(PermVar.SOLUTION_ADD)) {
            throw new MsgException("对不起，您没有编辑方案内容修改的权限。");
        }
        content.setStatus(true);
        content.setRecorder(curUser());
        content.setRecorderDate(DateUtil.now());
        dao.insertOrUpdate(content);
    }

    /**
     * 编辑方案修改
     * 
     * @param solution
     * @since chendan 2011-6-28
     */
    public void updateSolution(Solution solution){
        if (!roleBo.checkPermission(PermVar.SOLUTION_MODIFY)) {
            throw new MsgException("对不起，您没有编辑方案修改的权限。");
        }
        Solution solution2 = dao.get(Solution.class, solution.getId());
        if (solution2.getStatus() == 3 || solution2.getStatus() == 4) {
            throw new MsgException("编辑方案已经审核完毕，不能再进行修改");
        }
        solution2.setIssue(solution.getIssue());
        solution2.setName(solution.getName());
        solution2.setDate(solution.getDate());
        solution2.setRecorder(curUser());
        solution2.setRecorderDate(DateUtil.now());
        dao.insertOrUpdate(solution2);
    }

    /**
     * 编辑方案审核
     * 
     * @param review
     * @since chendan 2011-6-30
     */
    public void review(SolutionReview review){
        if (!roleBo.checkPermission(PermVar.SOLUTION_REVIEW1)
            && !roleBo.checkPermission(PermVar.SOLUTION_REVIEW2)
            && !roleBo.checkPermission(PermVar.SOLUTION_REVIEW3)) {
            throw new MsgException("对不起，您没有编辑方案审核的权限。");
        }
        Solution solution = dao.get(Solution.class, review.getSolution().getId());
        // 编辑方案状态为审核完毕或三审完毕的，不需要再进行审核
        if (solution.getStatus() == 3 || solution.getStatus() == 4) {
            throw new MsgException("编辑方案已经审核完毕，不需要再进行审核");
        }
        // 一审，status=0或-1,二审，status=1，三审,status=2
        if (review.getLevel() == 1
            && (solution.getStatus() != 0 && solution.getStatus() != -1)
            || review.getLevel() == 2
            && solution.getStatus() != 1
            || review.getLevel() == 3
            && solution.getStatus() != 2) {
            throw new MsgException("编辑方案审核时出现故障，请重新审核");
        }
        review.setAuditDate(DateUtil.now());
        review.setAuditUser(curUser());
        dao.insertOrUpdate(review);
        if (review.getResult() == 1) {
            // 审核结果为1，通过，进入下一级审核
            solution.setStatus(review.getLevel());
        } else if (review.getResult() == 2) {
            // 审核结果为2，不通过，退回到审核前状态
            solution.setStatus(-1);
        } else if (review.getResult() == 3) {
            // 审核结果为3，审核完毕，不需要再进行审核
            solution.setStatus(4);
        }
        dao.insertOrUpdate(solution);
    }

    @SuppressWarnings("unchecked")
    public void saveSolution(JSONObject obj){
        if (!roleBo.checkPermission(PermVar.SOLUTION_ADD)) {
            throw new MsgException("对不起，您没有编辑方案内容修改的权限。");
        }
        Long solid = obj.getLong("solution.id");
        // 删除原有的一些存储的信息
        List<SolutionItem> solutionItems = dao.find(SolutionItem.class, "solution.id", solid);
        for (SolutionItem solutionItem : solutionItems) {
            dao.delete(dao.find(SolutionContent.class, "solutionItem.id", solutionItem.getId()));
            dao.delete(solutionItem);
        }
        JSONArray items = obj.getJSONArray("items");
        for (Object tr : items) {
            JSONObject trJson = (JSONObject) tr;
            SolutionItem solutionItem = new SolutionItem();
            solutionItem.setOrder(JsonUtil.getJsonIntVal(trJson, "order", -1));
            solutionItem.setColum(JsonUtil.getJsonVal(trJson, "colum", null));
            solutionItem.setPageNo(JsonUtil.getJsonVal(trJson, "pageNo", null));
            solutionItem.setContent(JsonUtil.getJsonVal(trJson, "content", null));
            Long editorId = JsonUtil.getJsonLong(trJson, "editor.id", 0l);
            if (editorId.intValue() != 0) {
                solutionItem.setEditor(dao.get(User.class, editorId));
            }

            solutionItem.setSolution(dao.get(Solution.class, solid));
            dao.insertOrUpdate(solutionItem);
            List<JSONObject> lanmu = JsonUtil.getListItm(trJson, "items", Collections.EMPTY_LIST);
            for (Object td : lanmu) {
                JSONObject tdJson = (JSONObject) td;
                SolutionContent content = new SolutionContent();
                content.setOrder(JsonUtil.getJsonIntVal(tdJson, "order", 0));
                content.setPage(JsonUtil.getJsonVal(tdJson, "page", ""));
                content.setManuscript(dao.get(Manuscript.class, tdJson.getLong("manuscript.id")));
                content.setSolutionItem(solutionItem);
                content.setDesc(JsonUtil.getJsonVal(tdJson, "desc", ""));
                dao.insertOrUpdate(content);
            }
        }
    }

    public boolean isNewItem(Long id){
        return dao.findOne(SolutionItem.class, "solution.id", id) == null;
    }

    @ActionAnno(readOnly = true)
    public List<SolutionItem> getItems(Long id, boolean all){
        Criteria criteria = dao.initCriteria(SolutionItem.class);
        criteria.add(Restrictions.eq("solution.id", id));
        criteria.addOrder(Order.asc("order"));
        List<SolutionItem> items = criteria.list();
        for (SolutionItem item : items) {
            Criteria innerCria = dao.initCriteria(SolutionContent.class);
            innerCria.add(Restrictions.eq("solutionItem.id", item.getId()));
            innerCria.addOrder(Order.asc("order"));
            item.setContents(innerCria.list());
            try {
                item.setUserList(EditSolutionAction.createUserList(item.getEditor()));
            }
            catch (Exception e) {}
        }
        return items;
    }

    public synchronized String downZip(Long solutionId) throws Exception{
        List<SolutionItem> items = getItems(solutionId, true);
        String file = ArrayUtil.join(File.separator, WebOptUtil.APP_ARGS.getWebFileDir(), "WEB-INF", "tmp");
        for (SolutionItem solutionItem : items) {
            int order = solutionItem.getOrder();
            String no = solutionItem.getPageNo();
            String path = String.format("%s(%s)%s", Integer.toString(order), no, solutionItem.getColum());
            File folder = new File(file + File.separator + path);
            folder.mkdir();
            List<SolutionContent> contents = solutionItem.getContents();
            for (SolutionContent solutionContent : contents) {
                path = String.format(
                    "%s(%s)%s",
                    Integer.toString(solutionContent.getOrder()),
                    solutionContent.getPage(),
                    solutionContent.getDesc());
                String mPath = folder.getAbsolutePath() + File.separator + path;
                new File(mPath).mkdir();
                ManscripModel model = getModel(solutionContent);
                Map<String, Object> allData = new HashMap<String, Object>();
                allData.put("data", model);
                List<ImageModel> findImages = findImages(solutionContent.getManuscript(), mPath);
                allData.put("images", findImages);
                allData.put("imageSize", findImages.size());
                File content = new File(mPath + File.separator + "文章内容.txt");
                String contentVal = FtlUtil.render2Ftl(allData, "tpl/manuscript.html");
                FileUtils.writeStringToFile(content, contentVal, "UTF-8");
            }
        }
        String tmpZip = ArrayUtil.join(File.separator, WebOptUtil.APP_ARGS.getWebFileDir(), "WEB-INF", "contents.zip");
        ZipUtil.zip(tmpZip, file);
        FileUtils.deleteDirectory(new File(file));
        return tmpZip;
    }

    private List<ImageModel> findImages(Manuscript manuscript, String mPath) throws IOException{
        List<Manuscript2Image> images = dao.find(Manuscript2Image.class, "manuscript.id", manuscript.getId());
        List<ImageModel> lists = new ArrayList<ImageModel>();
        for (Manuscript2Image manuscript2Image : images) {
            ImageModel model = new ImageModel();
            Attachment a = attachmentBo.findAttch(manuscript2Image.getImageId());
            model.setDesc(a.getMark());
            model.setName(a.getName());
            model.setUpdateTime(DateUtil.format(a.getDate(), DateUtil.DATETIME_PATTERN));
            String imgSource = WebOptUtil.APP_ARGS.getUploadDir() + a.getPath() + File.separator + a.getLocalName();
            String target = mPath + File.separator + "(" + a.getMark() + ")" + a.getName();
            FileUtils.copyFile(new File(imgSource), new File(target));
            lists.add(model);
        }
        return lists;
    }

    private ManscripModel getModel(SolutionContent solutionContent){
        Manuscript manuscript = solutionContent.getManuscript();
        ManscripModel model = new ManscripModel(manuscript);
        model.setOtherAuthor(programmingBo.getManuscriptReporter(manuscript.getId()));
        model.setAudits(auditList(manuscript.getId()));
        return model;
    }

    private List<AuditList> auditList(Long id){
        Criteria criteria = dao.initCriteria(ManuScAudit.class);
        criteria.add(Restrictions.eq("manuscript.id", id));
        criteria.addOrder(Order.asc("level"));
        List<AuditList> list = new ArrayList<AuditList>();
        for (Object manuScAudit : criteria.list()) {
            ManuScAudit ms = (ManuScAudit) manuScAudit;
            AuditList a = new AuditList();
            a.setAuditor(ms.getAuditor().getName());
            a.setMark(ms.getRemark());
            list.add(a);
        }
        return list;
    }

    public static void main(String[] args){
        System.out.println(File.separator);
    }

    public void setProgrammingBo(ProgrammingBo programmingBo){
        this.programmingBo = programmingBo;
    }

    /**
     * 查询需要审核的编辑方案列表
     * 
     * @return
     * @since chendan 2011-7-11
     */
    public List<Solution> getAuditSolutions(){
        // 检查权限
        if (roleBo.checkPermission(PermVar.SOLUTION_REVIEW1)
            || roleBo.checkPermission(PermVar.SOLUTION_REVIEW2)
            || roleBo.checkPermission(PermVar.SOLUTION_REVIEW3)) {
            String hql = " from com.monlyu.vo.Solution s where s.status in (";
            if (roleBo.checkPermission(PermVar.SOLUTION_REVIEW1)) {
                hql += "-1,0,";
            }
            if (roleBo.checkPermission(PermVar.SOLUTION_REVIEW2)) {
                hql += "1,";
            }
            if (roleBo.checkPermission(PermVar.SOLUTION_REVIEW2)) {
                hql += "2,";
            }
            hql += "5)";
            return dao.find(hql);
        }
        return null;
    }
}
